﻿using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Unicode;
using System.Threading.Tasks;

namespace CacheExtensions
{
    public class RedisCache : ICache
    {

        /// <summary>
        /// 
        /// </summary>
        public IDatabase _database;
        /// <summary>
        /// 
        /// </summary>
        private ConnectionMultiplexer _connection;


        /*   /// <summary>
           /// 
           /// </summary>
           private readonly JsonSerializerOptions _jsonOptions;
   */

        private string _instance = "CMS";
        //  private readonly int _dataBase = 0;
        /// <summary>
        /// 
        /// </summary>
        public RedisCache(IOptions<CacheConfig> cacheConfig)
        {


            if (cacheConfig.Value.Type != CacheType.Redis)
            {
                throw new Exception("缓存类型设置错误");
            }
            // _dataBase = cacheConfig.CurrentValue.Type.Redis.DataBase;
            if(cacheConfig.Value.Redis==null) throw new Exception("连接字符串不能为空");
            _connection = ConnectionMultiplexer.Connect(cacheConfig.Value.Redis.ConnectionString);
            _instance = cacheConfig.Value.Prefix;
            _database = _connection.GetDatabase();
        }

         

        #region MyRegion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string GetKeyForRedis(string key)
        {
            return _instance + key;
        }

        /// <summary>
        /// 获取所有的KEY
        /// </summary>
        /// <returns></returns>
        public IEnumerable<string> GetAllKeys()
        {

            var endpoints = _connection.GetEndPoints();
            List<string> keyList = new List<string>();
            foreach (var ep in endpoints)
            {
                var server = _connection.GetServer(ep);
                var keys = server.Keys(_database.Database, GetKeyForRedis("*"));
                foreach (var item in keys)
                {
                    var v = item.ToString();

                    v = v.Substring(_instance.Length, v.Length - _instance.Length);
                    keyList.Add(v);
                }
            }
            return keyList;
        }

        /// <summary>
        /// 根据正则获取KEYS
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
        public IEnumerable<string> GetAllKeys(string pattern)
        {

            var endpoints = _connection.GetEndPoints();
            List<string> keyList = new List<string>();
            foreach (var ep in endpoints)
            {
                var server = _connection.GetServer(ep);
                var keys = server.Keys(_database.Database, GetKeyForRedis(pattern));
                foreach (var item in keys)
                {
                    var v = item.ToString();
                    v = v.Substring(_instance.Length, v.Length - _instance.Length);

                    keyList.Add(v);
                }
            }
            return keyList;
        }
        #region 验证缓存项是否存在
        /// <summary>
        /// 验证缓存项是否存在
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <returns></returns>
        public bool Exists(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            return _database.KeyExists(GetKeyForRedis(key));
        }
        /// <summary>
        /// 验证缓存项是否存在
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <returns></returns>
        public Task<bool> ExistsAsync(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            return _database.KeyExistsAsync(GetKeyForRedis(key));
        }
        #endregion

        #region 添加缓存
        /// <summary>
        /// 添加缓存
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="value">缓存Value</param>
        /// <returns></returns>
        public bool Add(string key, object value)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            CacheItem cacheItem = new CacheItem()
            {
                // AssemblyName = value.GetType().Assembly.FullName ?? throw new Exception("assembly.fullName 不能为空"),
                AssemblyQualifiedName = value.GetType().AssemblyQualifiedName ?? throw new Exception("type AssemblyQualifiedName can't be empty"),
            };
            if (value is string v)
            {
                cacheItem.Value = v;

                // return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(v), expiresIn);
            }
            else cacheItem.Value = JSON.Serialize(value);


            return _database.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JSON.Serialize(cacheItem)));

        }
        /// <summary>
        /// 添加缓存
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="value">缓存Value</param>
        /// <param name="expiresSliding">滑动过期时长（如果在过期时间内有操作，则以当前时间点延长过期时间,Redis中无效）</param>
        /// <param name="expiressAbsoulte">绝对过期时长</param>
        /// <returns></returns>
        public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            CacheItem cacheItem = new CacheItem()
            {
                // AssemblyName = value.GetType().Assembly.FullName ?? throw new Exception("assembly.fullName 不能为空"),
                AssemblyQualifiedName = value.GetType().AssemblyQualifiedName ?? throw new Exception("type AssemblyQualifiedName can't be empty"),
            };
            if (value is string v)
            {
                cacheItem.Value = v;

                // return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(v), expiresIn);
            }
            else cacheItem.Value = JSON.Serialize(value);


            return _database.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JSON.Serialize(cacheItem)), expiressAbsoulte);

        }
        /// <summary>
        /// 添加缓存
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="value">缓存Value</param>
        /// <param name="expiresIn">缓存时长</param>
        /// <param name="isSliding">是否滑动过期（如果在过期时间内有操作，则以当前时间点延长过期时间,Redis中无效）</param>
        /// <returns></returns>
        public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            CacheItem cacheItem = new CacheItem()
            {
                // AssemblyName = value.GetType().Assembly.FullName ?? throw new Exception("assembly.fullName 不能为空"),
                AssemblyQualifiedName = value.GetType().AssemblyQualifiedName ?? throw new Exception("type AssemblyQualifiedName can't be empty"),
            };
            if (value is string v)
            {
                cacheItem.Value = v;

                // return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(v), expiresIn);
            }
            else cacheItem.Value = JSON.Serialize(value);


            return _database.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JSON.Serialize(cacheItem)), expiresIn);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public Task<bool> AddAsync(string key, object value)
        {

            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            CacheItem cacheItem = new CacheItem()
            {
                // AssemblyName = value.GetType().Assembly.FullName ?? throw new Exception("assembly.fullName 不能为空"),
                AssemblyQualifiedName = value.GetType().AssemblyQualifiedName ?? throw new Exception("type AssemblyQualifiedName can't be empty"),
            };
            if (value is string v)
            {
                cacheItem.Value = v;

                // return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(v), expiresIn);
            }
            else cacheItem.Value = JSON.Serialize(value);


            return _database.StringSetAsync(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JSON.Serialize(cacheItem)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiresSliding"></param>
        /// <param name="expiressAbsoulte"></param>
        /// <returns></returns>
        public Task<bool> AddAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            CacheItem cacheItem = new CacheItem()
            {
                // AssemblyName = value.GetType().Assembly.FullName ?? throw new Exception("assembly.fullName 不能为空"),
                AssemblyQualifiedName = value.GetType().AssemblyQualifiedName ?? throw new Exception("type AssemblyQualifiedName can't be empty"),
            };
            if (value is string v)
            {
                cacheItem.Value = v;

                // return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(v), expiresIn);
            }
            else cacheItem.Value = JSON.Serialize(value);


            return _database.StringSetAsync(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JSON.Serialize(cacheItem)), expiressAbsoulte);

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiresIn"></param>
        /// <param name="isSliding"></param>
        /// <returns></returns>
        public Task<bool> AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            CacheItem cacheItem = new CacheItem()
            {
                // AssemblyName = value.GetType().Assembly.FullName ?? throw new Exception("assembly.fullName 不能为空"),
                AssemblyQualifiedName = value.GetType().AssemblyQualifiedName ?? throw new Exception("type AssemblyQualifiedName can't be empty"),
            };
            if (value is string v)
            {
                cacheItem.Value = v;

                // return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(v), expiresIn);
            }
            else cacheItem.Value = JSON.Serialize(value);


            return _database.StringSetAsync(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JSON.Serialize(cacheItem)), expiresIn);
        }
        /// <summary>
        /// 用键和值将某个缓存项插入缓存中，并指定基于时间的过期详细信息
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="value">缓存Value</param>
        /// <param name="seconds">缓存时长</param>
        public bool Add(string key, object value, int seconds = 7200)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            TimeSpan expiresIn = DateTime.Now.AddSeconds(seconds) - DateTime.Now;
            return Add(key, value, expiresIn);
        }

        #endregion

        #region hash 操作
        /// <summary>
        /// 将哈希表 key 中的字段 field 的值设为 value
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="field">字段</param>
        /// <param name="value">缓存Value</param>
        /// <returns></returns>
        public async Task<bool> HashSetAsync(string key, string field, object value)
        {
            return await _database.HashSetAsync(GetKeyForRedis(key), field, Encoding.UTF8.GetBytes(JSON.Serialize(value)));
        }
        /// <summary>
        ///  获取存储在哈希表中指定字段的值
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="field">字段</param>
        /// <returns></returns>
        public async Task<string> HashGetAsync(string key, string field)
        {
            return await _database.HashGetAsync(GetKeyForRedis(key), Encoding.UTF8.GetBytes(field));
        }


        /// <summary>
        ///  获取存储在哈希表中指定key的值
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <returns></returns>
        public async Task<HashEntry[]> HashGetAllAsync(string key)
        {
            return await _database.HashGetAllAsync(GetKeyForRedis(key));
        }
        /// <summary>
        ///  删除存储在哈希表中指定字段的值，不能删除key
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="field">字段</param>
        /// <returns></returns>
        public async Task<bool> HashDeleteAsync(string key, string field)
        {
            return await _database.HashDeleteAsync(GetKeyForRedis(key), Encoding.UTF8.GetBytes(field));
        }

        /// <summary>
        ///  批量删除存储在哈希表中指定字段的值，不能删除key
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="hashFields">字段</param>
        /// <returns></returns>
        public async Task<long> HashDeletesAsync(string key, RedisValue[] hashFields)
        {
            return await _database.HashDeleteAsync(GetKeyForRedis(key), hashFields);
        }
        #endregion

        #region List 操作
        /// <summary>
        /// 从底部插入数据
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="value">缓存Value</param>
        /// <returns></returns>
        public async Task<long> ListRightPushAsync(string key, object value)
        {
            return await _database.ListRightPushAsync(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JSON.Serialize(value)));//从底部插入数据
        }
        /// <summary>
        /// 从顶部插入数据
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="value">缓存Value</param>
        /// <returns></returns>
        public async Task<long> ListLeftPushAsync(string key, object value)
        {
            return await _database.ListLeftPushAsync(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JSON.Serialize(value)));//从顶部插入数据
        }
        /// <summary>
        /// 从顶部拿取数据
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <returns></returns>
        public string ListLeftPop(string key)
        {
            return _database.ListLeftPop(GetKeyForRedis(key));//从顶部插入数据
        }
        /// <summary>
        /// 从底部拿取数据
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <returns></returns>
        public string ListRightPop(string key)
        {
            return _database.ListRightPop(GetKeyForRedis(key));//从顶部插入数据
        }
        /// <summary>
        /// 移除与value相同的值
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="value">缓存Value</param>
        /// <returns></returns>
        public async Task<long> ListRemoveAsync(string key, object value)
        {
            return await _database.ListRemoveAsync(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JSON.Serialize(value)));
        }
        /// <summary>
        /// 获取list的值
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <returns></returns>
        public async Task<RedisValue[]> ListRangeAsync(string key)
        {
            return await _database.ListRangeAsync(GetKeyForRedis(key));
        }

        #endregion

        #region 删除缓存
        /// <summary>
        /// 删除缓存
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <returns></returns>
        public bool Remove(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            return _database.KeyDelete(GetKeyForRedis(key));
        }
        /// <summary>
        /// 批量删除缓存
        /// </summary>
        /// <param name="keys">缓存Key集合</param>
        /// <returns></returns>
        public void RemoveAll(IEnumerable<string> keys)
        {
            if (keys == null)
            {
                throw new ArgumentNullException(nameof(keys));
            }

            keys.ToList().ForEach(item => Remove(item));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Task<bool> RemoveAsync(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            return _database.KeyDeleteAsync(GetKeyForRedis(key));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        public Task RemoveAllAsync(IEnumerable<string> keys)
        {
            if (keys == null)
            {
                throw new ArgumentNullException(nameof(keys));
            }

            keys.ToList().ForEach(item => RemoveAsync(item));
            return Task.CompletedTask;
        }
        /// <summary>
        /// 使用通配符找出所有的key然后逐个删除
        /// </summary>
        /// <param name="pattern">通配符</param>
        public virtual void RemoveByPattern(string pattern)
        {
            foreach (var ep in _connection.GetEndPoints())
            {
                var server = _connection.GetServer(ep);
                var keys = server.Keys(pattern: GetKeyForRedis(pattern + "*"), database: _database.Database);
                // var keys = server.Keys(pattern: GetKeyForRedis("*" + pattern + "*"), database: _cache.Database);
                foreach (var key in keys)
                    _database.KeyDelete(key);
            }
        }


        /// <summary>
        /// 删除所有缓存
        /// </summary>
        public void RemoveCacheAll()
        {
            RemoveByPattern("");
        }
        #endregion

        #region 获取缓存

        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <returns></returns>
        public T? Get<T>(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            var o = this.Get(key);
            return o == null ? default(T) : (T)o;

            /*   var value = _cache.StringGet(GetKeyForRedis(key));

               if (!value.HasValue)
               {
                   return default(T);
               }
               if (typeof(T) == typeof(string))
               {

                   return (T)Convert.ChangeType(value, typeof(T));
               }
               try
               {
                   return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(value);
               }
               catch (Exception ex)
               {
                   Console.WriteLine($"缓存失败：{value}:{ex.ToString()}");
                   throw ex;
               }*/


        }



        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <returns></returns>
        public object? Get(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            var value = _database.StringGet(GetKeyForRedis(key));

            if (!value.HasValue)
            {
                return null;
            }
            var cacheItem = JSON.Deserialize<CacheItem>(value) ?? throw new Exception("CacheItem value can't be empty");

            var valueType = Type.GetType(cacheItem.AssemblyQualifiedName, true, true) ?? throw new Exception("type can't be empty");

            //  Type.GetType(cacheItem.AssemblyQualifiedName, true, true);

            if (cacheItem.AssemblyQualifiedName == typeof(string).AssemblyQualifiedName)
            {
                return cacheItem.Value?.ToString();
            }

            return JSON.Deserialize(cacheItem.Value?.ToString() ?? "", valueType);
        }



        /*  /// <summary>
          /// 
          /// </summary>
          /// <param name="key"></param>
          /// <returns></returns>
          public string Get(string key)
          {
              return (_cache.StringGet(GetKeyForRedis(key))).ToString() ?? "";
          }*/
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="Exception"></exception>
        public async Task<object?> GetAsync(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            var value = await _database.StringGetAsync(GetKeyForRedis(key));

            if (!value.HasValue)
            {
                return null;
            }
            var cacheItem = JSON.Deserialize<CacheItem>(value) ?? throw new Exception("CacheItem value can't be empty");

            var valueType = Type.GetType(cacheItem.AssemblyQualifiedName, true, true) ?? throw new Exception("type can't be empty");

            //  Type.GetType(cacheItem.AssemblyQualifiedName, true, true);

            if (cacheItem.AssemblyQualifiedName == typeof(string).AssemblyQualifiedName)
            {
                return cacheItem.Value?.ToString();
            }

            return JSON.Deserialize(cacheItem.Value?.ToString() ?? "", valueType);

        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public async Task<T?> GetAsync<T>(string key)
        {

            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            var o = await this.GetAsync(key);
            return o == null ? default(T) : (T)o;

        }

        /* /// <summary>
         /// 获取缓存集合
         /// </summary>
         /// <param name="keys">缓存Key集合</param>
         /// <returns></returns>
         public IDictionary<string, object?> GetAll(IEnumerable<string> keys)
         {
             if (keys == null)
             {
                 throw new ArgumentNullException(nameof(keys));
             }
             var dict = new Dictionary<string, object?>();

             keys.ToList().ForEach(item => dict.Add(item, Get(GetKeyForRedis(item))));

             return dict;
         }


         /// <summary>
         /// 
         /// </summary>
         /// <param name="keys"></param>
         /// <returns></returns>
         public Task<IDictionary<string, object?>> GetAllAsync(IEnumerable<string> keys)
         {

             throw new ArgumentNullException(nameof(keys));
         }*/
        #endregion

        #region 修改缓存
        /// <summary>
        /// 修改缓存
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="value">新的缓存Value</param>
        /// <returns></returns>
        public bool Replace(string key, object value)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            if (Exists(key))
                if (!Remove(key))
                    return false;

            return Add(key, value);

        }
        /// <summary>
        /// 修改缓存
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="value">新的缓存Value</param>
        /// <param name="expiresSliding">滑动过期时长（如果在过期时间内有操作，则以当前时间点延长过期时间）</param>
        /// <param name="expiressAbsoulte">绝对过期时长</param>
        /// <returns></returns>
        public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            if (Exists(key))
                if (!Remove(key))
                    return false;

            return Add(key, value, expiresSliding, expiressAbsoulte);
        }
        /// <summary>
        /// 修改缓存
        /// </summary>
        /// <param name="key">缓存Key</param>
        /// <param name="value">新的缓存Value</param>
        /// <param name="expiresIn">缓存时长</param>
        /// <param name="isSliding">是否滑动过期（如果在过期时间内有操作，则以当前时间点延长过期时间）</param>
        /// <returns></returns>
        public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            if (Exists(key))
                if (!Remove(key)) return false;

            return Add(key, value, expiresIn, isSliding);
        }


        #endregion
        #endregion


        #region MyRegion



        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public long Remove(params string[] key)
        {
            RedisKey[] list = new RedisKey[key.Length];
            for (int i = 0; i < key.Length; i++)
            {
                list[i] = new RedisKey(GetKeyForRedis(key[i]));
            }
            return _database.KeyDelete(list);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Task<long> RemoveAsync(params string[] key)
        {
            RedisKey[] list = new RedisKey[key.Length];
            for (int i = 0; i < key.Length; i++)
            {


                list[i] = new RedisKey(GetKeyForRedis(key[i]));
            }
            return _database.KeyDeleteAsync(list);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
        public async Task<long> RemoveByPatternAsync(string pattern)
        {
            var keys = GetAllKeys(pattern);

            return await RemoveAsync(keys.ToArray());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public async Task<long> RemoveStartWithAsync(string str)
        {

            var endpoints = _connection.GetEndPoints();
            List<string> keyList = new List<string>();
            foreach (var ep in endpoints)
            {
                var server = _connection.GetServer(ep);
                var keys = server.Keys(_database.Database, GetKeyForRedis(str) + "*");
                foreach (var item in keys)
                {
                    var v = item.ToString();
                    v = v.Substring(_instance.Length, v.Length - _instance.Length);
                    keyList.Add(v);
                }
            }

            return await RemoveAsync(keyList.ToArray());
        }

        public Task<IEnumerable<string>> GetKeys(string pattern)
        {
            return Task.FromResult(GetAllKeys(pattern));
        }


        public bool Set(string key, object value)
        {
            return Add(key, value);
        }

        public bool Set(string key, object value, TimeSpan expire)
        {
            return Add(key, value, expire);
        }

        public Task<bool> SetAsync(string key, object value)
        {
            return AddAsync(key, value);
        }

        public Task<bool> SetAsync(string key, object value, TimeSpan expire)
        {
            return AddAsync(key, value, expire);
        }

        #endregion
    }
}
